/******************************************************************************

                  版权所有 (C), LC.Ltd

 ******************************************************************************
  文 件 名   : Slot.c
  版 本 号   : 初稿
  作    者   : Jason
  生成日期   : 2012年8月22日
  最近修改   :
  
  功能描述   : slot对象 的操作.
  slot对象连接icc和character module以及connector对象。主要为应用层提供
  一个统一的抽象对象。所有对ICC的操作均需通过执行，slot隐藏了
  初始化connector，切换，以及应用icc参数等具体操作细节。
  
  函数列表   :
  修改历史   :
  1.日    期   : 2012年8月22日
    作    者   : Jason
    修改内容   : 创建文件

******************************************************************************/

/*----------------------------------------------*
 * 包含头文件                                   *
 *----------------------------------------------*/
#include <stdint.h>
#include "base.h"
#include "delay.h"
#include "error_code.h"
#include "slot.h"
#include "icc_core.h"
#include "clock_countor.h"
#include "Protocol.h"
#include "power_on.h"
#include "Light.h"
#include "etu_timer.h"
#include "character_module.h"
#include "icc.h"
#include "Bsp_Sleep.h"

/*----------------------------------------------*
 * 外部变量说明                                 *
 *----------------------------------------------*/
extern	character_module_t *CharacterModule[1];

/*----------------------------------------------*
 * 外部函数原型说明                             *
 *----------------------------------------------*/

/*----------------------------------------------*
 * 内部函数原型说明                             *
 *----------------------------------------------*/

/*----------------------------------------------*
 * 全局变量                                     *
 *----------------------------------------------*/
 
slot_t Slot[1];

/*----------------------------------------------*
 * 模块级变量                                   *
 *----------------------------------------------*/

/*----------------------------------------------*
 * 常量定义                                     *
 *----------------------------------------------*/

/*----------------------------------------------*
 * 宏定义                                       *
 *----------------------------------------------*/
	
void Slot_Init(void)
{
	uint32_t i;
	
	IccPool_Init();
	for(i = 0; i < SIZE_OF_ARRAY(Slot); i++)
	{
		Slot[i].icc = IccPool_Get();
		Slot[i].icc->work_mode = 1;
		Slot[i].connector = Connector_Get(0);
		Slot[i].module = CharacterModule[i];
		Slot[i].module->hw->number = i;
		Slot[i].number = i;
	}
}

static void character_module_config(character_module_t *module, icc_t *icc)
{
	CharacterModule_Reset(module);
	CharacterModule_ConfigByteDirection(module, icc->byte_direction);
	CharacterModule_SetETU(module, icc->FiDi);
	CharacterModule_ConfigRetransmit(module, icc->retransmit_times);
	CharacterModule_SetStopbits(module, icc->stop_bit);
	CharacterModule_SetOppositiveGuardtime(module, icc->oppositive_guardtime);
}


static void slot_config(slot_t *slot)
{
	Connector_Switch(slot->connector, slot->number);
}

/*****************************************************************************
 函 数 名  : Slot_Connect
 功能描述  : 连接某个slot，建立与ICC的通信通道
 输入参数  : slot_t *slot  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2012年8月22日
    作    者   : Jason
    修改内容   : 新生成函数

*****************************************************************************/
uint32_t Slot_Connect(slot_t *slot)
{
	icc_t *icc;
	character_module_t *module;
	
	icc = slot->icc;
	module = slot->module;
	
	slot_config(slot);
	character_module_config(module, icc);
	return 0;
}


/*****************************************************************************
 函 数 名  : Slot_CheckCardPresent
 功能描述  : 检测卡槽状态，并根据状态分配或释放ICC
 输入参数  : slot_t *slot  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2012年8月22日
    作    者   : Jason
    修改内容   : 新生成函数

*****************************************************************************/
uint32_t Slot_CheckCardPresent(slot_t *slot)
{
	uint8_t state;
	uint8_t number = slot->number;
	connector_t *con = slot->connector;
	
	state = Connector_CheckCardPresent(con, number);

	if(state != 0)
	{
		if(slot->icc == (icc_t *)0)
		{
			icc_t *icc;
			icc = IccPool_Get();
			if(icc != (icc_t *)0)
			{
				slot->icc = icc;
			}
		}
	}
	else
	{
		if(slot->icc != (icc_t *)0)
		{
			IccPool_Put(slot->icc);
			slot->icc = (icc_t *)0;
		}
	}
	
	return state;
}

uint32_t Slot_CheckCard(uint8_t number)
{
	return Connector_CheckCardPresent(Slot[number].connector, Slot[number].number);
//		return 1;
}

uint32_t Slot_PowerOff(slot_t *slot)
{
	connector_t *con = slot->connector;
	icc_t *icc = slot->icc;
	//return physical_deactive(0);
	
	if((uint32_t)icc != 0u)
	{
		icc->active_flag = 0;		
	}
	slot_config(slot);
	Connector_SetResetState(con, CON_LOW);
	delay_us(10);
	Connector_ClockDeactive(con);
	delay_us(10);
	Connector_SetVCC(con, 0);
	//delay_ms(1);
	//HardwareModule_ClockDisable(slot->module->hw);
	return NO_ERR;
}

static void config_IO_high(slot_t *slot)
{
	character_module_t *module = slot->module;
	connector_t *con = slot->connector;
	
	Connector_ConfigIO(con, CON_IO_TRANSPARENT);
	CharacterModule_Flush(module);	
}

static void reset_low_holdtime(void)
{
	ETUTimer_Wait(115, 0x11); // 115 * 372 = 42780 clock;
}

uint32_t Slot_ColdReset(slot_t *slot, uint8_t voltage)
{
	uint32_t ret;
	
	connector_t *con = slot->connector;
	
	Slot_PowerOff(slot);
	config_IO_high(slot);
	BSP_Sleep_Ms(15);
	ret = Connector_SetVCC(con, voltage);
	if(ret != NO_ERR)
	{
		return ret;
	}
	BSP_Sleep_Ms(3);
	Connector_ClockActive(con);
	/*
	EMV4.3 Book1 6.1.3.1
	The terminal shall maintain RST in state L through time T0 and for a period 
	of between 40,000 and 45,000 clock cycles following time T0 to time T1, when 
	it shall set RST to state H. 
	*/
	reset_low_holdtime();

	Connector_SetResetState(con, CON_HIGH);
	return ret;
}

void Slot_WarmReset(slot_t *slot)
{
	connector_t *con = slot->connector;

	Connector_SetResetState(con, CON_LOW);
	/*
	The terminal shall maintain RST in state L from time T0' for a period of 
	between 40,000 and 45,000 clock cycles following time T0' to time T1', when it
	shall set RST to state H. 
	*/
	reset_low_holdtime();
	Connector_SetResetState(con, CON_HIGH);
}

uint32_t Slot_PowerOn(slot_t *slot, uint8_t atr[], uint8_t *atr_len)
{
	uint32_t ret;
	icc_t *icc = slot->icc;

	if((uint32_t)icc == 0u)
	{
		return ERR_CARD_ABSENT;
	}
	
	ret = ActivateICC(slot, atr, atr_len);

	if(ret == NO_ERR)
	{
		ICC_Config(icc);
		
		if(icc->protocol_type == 1)
		{
			ret = Slot_Connect(slot);
			if(NO_ERR == ret)
			{
				ret = BlockProtocol_IFSDRequest(slot);
			}
		}		
	}

	if(ret != NO_ERR)
	{
		Slot_PowerOff(slot);
	}
	else
	{
		icc->active_flag = 1;
	}
	
	return ret;
}

uint32_t Slot_ExchangAPDU(slot_t *slot, uint8_t c_apdu[], uint32_t c_apdu_len, uint8_t r_apdu[], uint32_t *r_apdu_len)
{
	uint32_t ret;
	
	icc_t *icc = slot->icc;
	
	if((uint32_t)icc == 0u)
	{
		return ERR_CARD_ABSENT;
	}

	if(icc->active_flag == 0)
	{
		return ERR_CARD_INACTIVE;
	}
	
    Slot_Connect(slot);
    
	if(icc->protocol_type == 0)
	{
		ret = CharacterProtocol_ExchangeApdu(slot, c_apdu, c_apdu_len, r_apdu, r_apdu_len);
	}
	else
	{
		ret = BlockProtocol_ExchangeApdu(slot, c_apdu, c_apdu_len, r_apdu, r_apdu_len);
	}

	return ret;
}





